/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package com.xy.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.tencentcloudapi.faceid.v20180301.models.IdCardVerificationResponse;
import com.tencentcloudapi.faceid.v20180301.models.ImageRecognitionResponse;
import com.tencentcloudapi.iai.v20200303.models.CreatePersonResponse;
import com.tencentcloudapi.iai.v20200303.models.DetectFaceResponse;
import com.tencentcloudapi.iai.v20200303.models.GetPersonBaseInfoResponse;
import com.xy.config.AipFaceClient;
import com.xy.constants.RedisConstant;
import com.xy.entity.*;
import com.xy.excel.ErrorViewerExcel;
import com.xy.service.*;
import com.xy.tx.TxCommon;
import com.xy.vo.PrintTemplateVO;
import com.xy.vo.ViewerVO;
import com.xy.excel.ViewerExcel;
import com.xy.mapper.ViewerMapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.core.tool.utils.*;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.core.mp.base.BaseServiceImpl;

import java.time.LocalDateTime;
import java.time.Month;
import java.time.format.TextStyle;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 票证管理 服务实现类
 *
 * @author BladeX
 * @since 2023-07-18
 */
@Slf4j
@Service

public class ViewerServiceImpl extends BaseServiceImpl<ViewerMapper, ViewerEntity> implements IViewerService {
	@Autowired
	private  IViewerSortService viewerSortService;
	@Autowired
	@Lazy
	private  IExhibitionService exhibitionService;

	@Autowired
	private  BladeRedis bladeRedis;

	@Override
	public IPage<ViewerVO> selectViewerPage(IPage<ViewerVO> page, ViewerVO viewer) {
		return page.setRecords(baseMapper.selectViewerPage(page, viewer));
	}


	@Override
	public List<ViewerExcel> exportViewer(Wrapper<ViewerEntity> queryWrapper) {
		List<ViewerExcel> viewerList = baseMapper.exportViewer(queryWrapper);
		//viewerList.forEach(viewer -> {
		//	viewer.setTypeName(DictCache.getValue(DictEnum.YES_NO, Viewer.getType()));
		//});
		return viewerList;
	}

	@Override
	public void importUser(List<ViewerExcel> excelList) {
		/**
		 * 1、创建导入留痕数据
		 * 2、用户分类不存在、创建分类
		 * 3、数据验证不合格的数据支持导出
		 * 4、生成用户
		 */
		//分割集合
		int limit = 500;
		int maxSize = (excelList.size() + limit - 1) / limit;
		List<ExhibitionEntity> exhibitionList = exhibitionService.queryExhibition();
		Map<Long, List<ExhibitionEntity>> listMap = exhibitionList.stream().collect(Collectors.groupingBy(ExhibitionEntity::getId));
		List<Long> listIds = exhibitionList.stream().map(ExhibitionEntity::getId).collect(Collectors.toList());
		List<ErrorViewerExcel> errorViewer = new ArrayList<>();
		Stream.iterate(0, n -> n + 1).limit(maxSize).parallel().forEach(a -> {
			List<ViewerExcel> list = excelList.stream().skip(a * limit).limit(limit).parallel().collect(Collectors.toList());
			List<ViewerEntity> updateList = new ArrayList<>();
			List<ViewerEntity> saveList = new ArrayList<>();

			list.forEach(o -> {
				if (!listMap.containsKey(o.getExhibitionId())) {
					ErrorViewerExcel viewerExcel = BeanUtil.copy(o, ErrorViewerExcel.class);
					viewerExcel.setRemake("展会不存在");
					errorViewer.add(viewerExcel);
				}
				ViewerEntity viewerEntity = BeanUtil.copy(o, ViewerEntity.class);
				Long typeId = this.saveViewerType(o.getSortName(), o.getExhibitionId());
				viewerEntity.setViewerTypeId(typeId);
				viewerEntity.setSourceFrom("2");
				viewerEntity.setViewerStatus(0);
				if (dateList(viewerEntity, listIds, null, updateList, errorViewer)) {
					return;
				}
				saveList.add(viewerEntity);
			});
			if (CollectionUtil.isNotEmpty(updateList)) {
				this.updateBatchById(updateList);
			}
			if (CollectionUtil.isNotEmpty(saveList)) {
				this.saveBatch(saveList);
			}
		});
	}

	/**
	 * 判断数据库是否存在
	 *
	 * @param o
	 * @param
	 * @param listIds
	 * @param typeId
	 * @param errorViewerList
	 * @return
	 */
	private boolean dateList(ViewerEntity o, List<Long> listIds, Long typeId, List<ViewerEntity> updateList, List<ErrorViewerExcel> errorViewerList) {
		if (StringUtil.isBlank(o.getIdCard())) {
			//  身份证号为空
			ErrorViewerExcel ViewerExcel = BeanUtil.copy(o, ErrorViewerExcel.class);
			ViewerExcel.setRemake("身份证号为空");
			errorViewerList.add(ViewerExcel);
			return true;
		}
		if (StringUtil.isNotBlank(o.getTwoCode())) {
			ViewerEntity viewerEntity = null;//bladeRedis.get(RedisConstant.CASH_CARD_NO.concat(o.getCardNo()));
//			if (viewerEntity == null) {
			viewerEntity = this.queryViewerByTwoCode(o, null, Arrays.asList(o.getExhibitionId()), typeId);
			log.info("进入数据库查询、卡号：{}", o.getTwoCode());
//			}
			boolean data = data(viewerEntity, o, updateList, errorViewerList);
			//为true则出去、flase 进行下面验证
			if (data) {
				return true;
			}
		}
		if (StringUtil.isNotBlank(o.getSwipeCard())) {
			ViewerEntity viewerEntity = null;// bladeRedis.get(RedisConstant.CASH_swipeCard_NO.concat(o.getSwipeCard()));
//			if (viewerEntity == null) {
			viewerEntity = this.queryViewerBySwipeCard(o, null, Arrays.asList(o.getExhibitionId()), typeId);
			log.info("进入数据库查询、swipeCard号：{}", o.getSwipeCard());
//			}
			//为true则出去、flase 进行下面验证
			boolean data = data(viewerEntity, o, updateList, errorViewerList);
			if (data) {
				return true;
			}
		}

		return false;
	}

	/**
	 * 数据组装
	 *
	 * @param viewerEntity
	 */
	private boolean data(ViewerEntity viewerEntity, ViewerEntity o, List<ViewerEntity> updateList, List<ErrorViewerExcel> errorViewerExcels) {
		if (viewerEntity != null && !viewerEntity.getExhibitionId().equals(o.getExhibitionId())) {
			//与其他展会冲突
			ErrorViewerExcel ViewerExcel = BeanUtil.copy(o, ErrorViewerExcel.class);
			ViewerExcel.setRemake("与同期展会数据冲突");
			errorViewerExcels.add(ViewerExcel);
			return true;
		}
		if (viewerEntity != null) {
			BeanUtil.copy(o, viewerEntity);
			updateList.add(viewerEntity);
			return true;
		}
		return false;
	}

	/**
	 * 查询票证类型、没有则保存
	 *
	 * @param viewerTypeName
	 * @param exhibitionId
	 * @return
	 */
	public Long saveViewerType(String viewerTypeName, Long exhibitionId) {
		//查询票证类型
		String key = RedisConstant.TYPE_ID_EX_TYPE_NAME.concat(viewerTypeName).concat(exhibitionId + "");
		Long typeId = bladeRedis.get(key);
		if (typeId == null) {
			ViewerSortEntity viewerSortEntity = queryViewerType(viewerTypeName, exhibitionId);
			if (viewerSortEntity == null) {
				viewerSortEntity = BeanUtil.newInstance(ViewerSortEntity.class);
				viewerSortEntity.setExhibitionId(exhibitionId);
				viewerSortEntity.setSortName(viewerTypeName);
				viewerSortService.save(viewerSortEntity);
				bladeRedis.set(key, viewerSortEntity.getId());
				return viewerSortEntity.getId();
			}
			bladeRedis.set(key, viewerSortEntity.getId());
			return viewerSortEntity.getId();
		}
		return typeId;
	}

	/**
	 * 查询票证
	 *
	 * @param viewerSortName
	 * @param exhibitionId
	 * @return
	 */
	public ViewerSortEntity queryViewerType(String viewerSortName, Long exhibitionId) {
		LambdaQueryWrapper<ViewerSortEntity> queryWrapper = Wrappers.lambdaQuery();
		queryWrapper.eq(StringUtil.isNotBlank(viewerSortName), ViewerSortEntity::getSortName, viewerSortName);
		queryWrapper.eq(ViewerSortEntity::getExhibitionId, exhibitionId);
		return viewerSortService.getOne(queryWrapper);
	}

	/**
	 * 导出用户
	 *
	 * @param viewer
	 * @return
	 */
	@Override
	public List<ViewerExcel> exportQuery(ViewerEntity viewer) {
		return baseMapper.exportQuery(viewer);
	}

	/**
	 * 信息采集
	 *
	 * @param viewer
	 * @return
	 */
	@Override
	public boolean collect(ViewerEntity viewer) throws Exception{
		//查询证件信息
		LambdaQueryWrapper<ViewerEntity> queryWrapper = Wrappers.<ViewerEntity>query().lambda().eq(ViewerEntity::getExhibitionId, viewer.getExhibitionId());

		queryWrapper.gt(Func.isNotEmpty(viewer.getId()),ViewerEntity::getId, viewer.getId());
		queryWrapper.orderByAsc(ViewerEntity::getId);
		List<ViewerEntity> v = this.list(queryWrapper);
//		log.info("查询证件信息成功 viewer={}", viewer);
//		if (ViewerEntity == null) {
//			throw new ServiceException("证件信息不存在!");
//		}
//		viewer.setHeadUrl(viewer.getHeadUrl().replace("https://picture.city-cloud.cn","http://172.30.101.203:9000"));
//		if ("1".equals(viewer.getCardType()) && viewer.getIsVerify() == 0 ) {
//			//国内人员
//			if (StringUtil.isNotBlank(viewer.getHeadUrl())) {
//				//三要素校验
//				ImageRecognitionResponse imageRecognitionResponse = TxCommon.imageRecognition(viewer.getName(), viewer.getIdCard(), viewer.getHeadUrl());
//				if (!"Success".equals(imageRecognitionResponse.getResult())) {
//					throw new ServiceException(imageRecognitionResponse.getDescription());
//				}
//			} else {
//				//二要素校验
//				IdCardVerificationResponse idCardVerificationResponse = TxCommon.idCardVerification(viewer.getName(), viewer.getIdCard());
//				if (!"0".equals(idCardVerificationResponse.getResult())) {
//					throw new ServiceException(idCardVerificationResponse.getDescription());
//				}
//			}
//		}
		v.forEach(v1 -> {

			//人脸注册
			if (StringUtil.isBlank(v1.getHeadUrl())) {
				return;
			}
			GetPersonBaseInfoResponse personInfo = TxCommon.getPersonInfo(Func.toStr(v1.getId()));
			if (personInfo == null) {
				log.info("人员ID{} ", v1.getId());
				CreatePersonResponse person = TxCommon.createPerson(v1.getHeadUrl(), String.valueOf(v1.getExhibitionId()), String.valueOf(v1.getId()), v1.getName());
				if(person == null){
					log.info("腾讯人脸注册失败");
				}
			}

		});

//			//人脸检测
//			DetectFaceResponse response = TxCommon.detectFace(viewer.getHeadUrl());
//
//			if (response == null) {
//				throw new ServiceException("未检测到人脸");
//			}
//
//			if (viewer.getFaceRegister() == 0) {
				//腾讯人脸注册

//				//百度人脸注册
//				AipFaceClient.deleteFace(String.valueOf(viewer.getId()), String.valueOf(viewer.getExhibitionId()));
//				boolean result = AipFaceClient.addFace(String.valueOf(viewer.getId()), String.valueOf(viewer.getExhibitionId()), viewer.getHeadUrl());
//				if(!result){
//					throw new ServiceException("百度人脸注册失败");
//				}
//			}
//		}
//		//更新数据
//		updateById(viewer);
//		log.info("更新证件信息成功 viewer={}", viewer);

		return true;
	}

	/**
	 * 获取打印数据
	 *
	 * @param req
	 * @return
	 */
	@Override
	public PrintTemplateVO getPrintData(GetPrintDataEntity req) {
		//PrintTemplateEntity template = templateService.getById(req.getTemplateId());
		//List<PrintTemplateDetailEntity> details = templateDetailService.getTemplateDetails(req.templateId);
		//if (template == null || details == null) {
		//	throw new ServiceException("打印模板未配置");
		//}
		//PrintTemplateVO templateVO = BeanUtil.copy(template, PrintTemplateVO.class);
		//templateVO.setTemplateDetails(details);
		//ViewerEntity viewerEntity = getById(req.certificatesId);
		//if (viewerEntity == null) {
		//	throw new ServiceException("证件不存在");
		//}
		//List<TimeStageEntity> admissionTime = timeStageService.getTimeStage(req.certificatesId);
		//viewerEntity.setTimeStageList(admissionTime);
		//convertPrintData(templateVO, viewerEntity);
		//return templateVO;
		return  null;
	}

	private void convertPrintData(PrintTemplateVO templateVO, ViewerEntity viewer) {
		ViewerSortEntity viewerSort = viewerSortService.getById(viewer.getViewerTypeId());
		for (PrintTemplateDetailEntity detail : templateVO.getTemplateDetails()) {

			switch (detail.getField()) {
				case "name":
					detail.setValue(viewer.getName());
					break;
				case "validTime":
					List<TimeStageEntity> timeStageList = viewer.getTimeStageList();
					detail.setValue(viewerSort.getSortName());
					if (CollectionUtil.isNotEmpty(timeStageList)) {
						TimeStageEntity timeStageEntity = timeStageList.get(0);
						Date startTime = timeStageEntity.getStartTime();
						Date endTime = timeStageEntity.getEndTime();
						if (endTime != null && new Date().after(endTime)) {
							throw new ServiceException("票证已过期");
						}
						if (startTime != null && viewerSort.getSortName().contains("观众")) {
							LocalDateTime localDateTime = DateUtil.fromDate(startTime);
							Month month = localDateTime.getMonth();
							int dayOfMonth = localDateTime.getDayOfMonth();
							String displayName = month.getDisplayName(TextStyle.SHORT, Locale.ENGLISH);
							detail.setValue("当天有效 Vaild on " + displayName + "." + dayOfMonth);
						}
					}
					break;
				case "photo":
					detail.setValue(viewer.getHeadUrl());
				case "cardNo":
					detail.setValue(viewer.getTwoCode());
			}
		}
	}

	public static void main(String[] args) {

	}

	/**
	 * 通过Card
	 *
	 * @param
	 * @return
	 */
	public ViewerEntity queryViewerByTwoCode(ViewerEntity viewerEntity, Long exhibitionId, List<Long> listIds, Long typeId) {
		return queryViewerCount(null, viewerEntity.getTwoCode(), null, exhibitionId, listIds, typeId);
	}

	/**
	 * 通过swipeCard
	 *
	 * @param exhibitionId
	 * @return
	 */
	public ViewerEntity queryViewerBySwipeCard(ViewerEntity viewerEntity, Long exhibitionId, List<Long> listIds, Long typeId) {
		return queryViewerCount(viewerEntity.getSwipeCard(), null, null, exhibitionId, listIds, typeId);
	}

	/**
	 * 查询用户
	 *
	 * @param swipeCard
	 * @param twoCode
	 * @param idCard
	 * @param typeId
	 * @param exhibitionId
	 * @return
	 */
	@Override
	public ViewerEntity queryViewerCount(String swipeCard, String twoCode, String idCard, Long exhibitionId, List<Long> listIds, Long typeId) {
		LambdaQueryWrapper<ViewerEntity> ViewerEntityLambdaQueryWrapper = Wrappers.lambdaQuery();
		ViewerEntityLambdaQueryWrapper.select(ViewerEntity::getId, ViewerEntity::getName, ViewerEntity::getExhibitionId,ViewerEntity::getIdCard);
		ViewerEntityLambdaQueryWrapper.eq(StringUtil.isNotBlank(swipeCard), ViewerEntity::getSwipeCard, swipeCard);
		ViewerEntityLambdaQueryWrapper.eq(StringUtil.isNotBlank(twoCode), ViewerEntity::getTwoCode, twoCode);
		ViewerEntityLambdaQueryWrapper.in(StringUtil.isBlank(idCard), ViewerEntity::getExhibitionId, listIds);
		return this.getOne(ViewerEntityLambdaQueryWrapper);
	}

	@Override
	public List<ViewerEntity> queryViewerIdCard(String idCard, Long exhibitionId) {
		LambdaQueryWrapper<ViewerEntity> ViewerEntityLambdaQueryWrapper = Wrappers.lambdaQuery();
		ViewerEntityLambdaQueryWrapper.select(ViewerEntity::getId, ViewerEntity::getName, ViewerEntity::getExhibitionId,
			ViewerEntity::getViewerTypeId,ViewerEntity::getHeadUrl,ViewerEntity::getTwoCode,ViewerEntity::getCompany,
			ViewerEntity::getViewerStatus,ViewerEntity::getIdCard,ViewerEntity::getUpdateTime);
		ViewerEntityLambdaQueryWrapper.eq(StringUtil.isNotBlank(idCard), ViewerEntity::getIdCard, idCard);
		ViewerEntityLambdaQueryWrapper.eq(ViewerEntity::getExhibitionId, exhibitionId);
		return this.list(ViewerEntityLambdaQueryWrapper);
	}

	@Override
	public List<ViewerEntity> add() {
		return  baseMapper.add();
	}
}
